/****************************************************
	文件：LogMemento.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/7/11 17:8:51
	功能：打印备忘录
*****************************************************/

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading;

namespace HTSpider
{
    public class LogMemento
    {
        public enum LogMementoType
        {
            Log = 0,
            Warning = 1,
            Error = 2,
            Max = 3,
        }
        /// <summary>
        /// Log日志队列
        /// </summary>
        private Queue<string> mLogQue;
        /// <summary>
        /// 存错的文件夹路径
        /// </summary>
        private string mSaveDirctoryPath;
        /// <summary>
        /// 存储的文件名（带后缀）
        /// </summary>
        private string mSaveName;
        /// <summary>
        /// 将Log日志写入本地的线程
        /// </summary>
        private Thread mSaveLogMementoThread;

        ~LogMemento()
        {
            OnDestroy();
        }
        public LogMemento(string saveDirctoryPath)
        {
            mSaveDirctoryPath = saveDirctoryPath;
            mLogQue = new Queue<string>();
            mSaveLogMementoThread = new Thread(SaveLogMementoThread);
            mSaveLogMementoThread.IsBackground = true;
            mSaveLogMementoThread.Start();
            mSaveName = GetSaveName();
        }
        public void Init()
        {
            Helper.CreateDirectory(mSaveDirctoryPath);
            Logger.Log("LogMemento init done.");
        }
        public void OnDestroy()
        {
            SaveImmediately();
            Clear();
            if (mSaveLogMementoThread.IsAlive)
            {
                mSaveLogMementoThread.Abort();
                mSaveLogMementoThread = null;
            }
        }

        public void Add(string logMsg, LogMementoType mementoType)
        {
            if (string.IsNullOrEmpty(logMsg)) return;
            switch (mementoType)
            {
                case LogMementoType.Log:
                    logMsg = string.Concat(Helper.GetNowTimeStr(), "   ", "Log : ", logMsg, "\n");
                    break;
                case LogMementoType.Warning:
                    logMsg = string.Concat(Helper.GetNowTimeStr(), "   ", "Warning : ", logMsg, "\n");
                    break;
                case LogMementoType.Error:
                    logMsg = string.Concat(Helper.GetNowTimeStr(), "   ", "Error : ", logMsg, "\n");
                    break;
                case LogMementoType.Max:
                    Logger.Error(" 尚未定义此 Logger 类型！");
                    return;
            }
            lock (mLogQue)
            {
                mLogQue.Enqueue(logMsg);
            }
        }
        public void SaveImmediately()
        {
            if (mLogQue.Count <= 0) return;
            SaveToLocal();
        }
        public void SaveToLocal()
        {
            if (Directory.Exists(mSaveDirctoryPath) == false) return;
            string savePath = Path.Combine(mSaveDirctoryPath, mSaveName);
            try
            {
                string content = string.Empty;
                if (File.Exists(savePath))
                {
                    content = File.ReadAllText(savePath);
                }
                StringBuilder stringBuilder = new StringBuilder();
                stringBuilder.Append(content);
                while (mLogQue.Count > 0)
                {
                    lock (mLogQue)
                    {
                        stringBuilder.Append(mLogQue.Dequeue());
                    }
                }
                File.WriteAllText(savePath, stringBuilder.ToString(), Encoding.UTF8);
            }
            catch (Exception e)
            {
                Logger.ErrorFormat("LogMemento SaveToLocal Error !\nException : {0}", e.ToString());
            }
        }
        public void Clear()
        {
            lock (mLogQue)
            {
                mLogQue.Clear();
            }
        }

        private void SaveLogMementoThread()
        {
            while (true)
            {
                if (mLogQue.Count < Consts.LOGMEMENTO_SAVE_THRESHOLD) continue;
                SaveToLocal();
                mSaveName = GetSaveName();
            }
        }
        private string GetSaveName()
        {
            return string.Concat(DateTime.Now.Year, "-", DateTime.Now.Month, "-", DateTime.Now.Day, "--", DateTime.Now.Hour, "-", DateTime.Now.Minute, "-", DateTime.Now.Second, ".txt");
        }
    }
}
